Market basket
1. Problema¶
El siguiente análisis corresponde a las cotizaciones y facturaciones de repuestos en SKC y como se comportan estas en relación a los ítems que poseen, específicamanete a que grupo de productos estan involucrados y como se comporta cada uno en los dos diferentes escenarios cotizado y facturado. La principal idea es determinar que productos finalmente se dejan fuera al momento de la factura e identificarlos para en un posterior análisis buscar la causa de la razón por la cuál desaparecen de la compra final. El análisis se basa principalmente por grupo de productos ya que por artículo considerando el negocio de repuestos no entrega una visión clara ya que muchos repuestos solo se venden una vez para casos particulares a diferencia de los ítems que se venden con frecuencia para mantenciones, las reparaciones son diferentes e involucran items que probablemente se utilicen en solo para esa ocasión.
library("arules")
library("plyr")
library("ggplot2")
library("knitr")
library("Matrix")
library("dplyr")
library("arulesViz")
library("repr")
2. Análisis exploratorio¶
Seleccionamos el directorio donde estan los archivos .txt y los leemos con la función read.csv. Para ello utilizaremos dos archivos uno con las cotizaciones y otro con las facturas.
setwd("C:/Users/alfredo/Documents")
df_cot<-read.csv(file="cotizado.txt", header=T, sep="\t", dec="," )
df_ven<-read.csv(file="ventas.txt", header=T, sep="\t", dec="," )
Revisamos las primeras cinco filas de las cotizaciones y facturas.
head(df_cot,5)
head(df_ven, 5)
Revisamos el total de filas y columnas para las cotizaciones y facturas.
dim(df_cot)
dim(df_ven)
Revisamos si los dataframes contienen datos missing.
sum(is.na(df_cot[c('Cantidad', 'total')]))
sum(is.na(df_ven[c('cantidad', 'ingreso')]))
Tenemos 2 datos missing en las cotizaciones, para ello no utilizaremos estos datos y procederemos a eliminarlos del dataframe.
df_cot<-na.omit(df_cot)
Realizamos un summary para revisar los estadísticos básicos de cada dataframe.
summary(subset(df_cot, select=c(Cantidad, ingreso)))
Para las cotizaciones tenemos que la mínima cantidad cotizada es de 0 ítem con una media de 3.386, una mediana de 1 y el máximo es de 784 unidades. Para los montos cotizados el mínimo es de 0 USD lo cual representa un outlier, la media es de 492,45 USD y el monto máximo es de 209.515 USD.
summary(subset(df_ven, select=c(cantidad, ingreso)))
Para la facturación tenemos que la mínima cantidad facturada es de -1 ítem (probablemente se debe a una devolución) con una media de 3.198, una mediana de 1 y el máximo es de 784 unidades. Para los montos facturados el mínimo es de -314 USD lo cual representa una nota de crédito, la media es de 218,04 USD y el monto máximo es de 14.779 USD.
Gráficamos la cantidad de items por cotizaciones.
options(repr.plot.width=7, repr.plot.height=3)
df_cot %>%
group_by(Doc_vtas) %>%
summarize(n_items = sum(Cantidad)) %>%
ggplot(aes(x=n_items))+
geom_histogram(fill="indianred", bins = 300) +
labs(title="ítems por cotizaciones") +
geom_rug()+
coord_cartesian(xlim=c(0,50))
La mayoría de los clientes cotiza menos de 10 ítems por cada cotización emitida ya que existen mas de 4.000 cotizaciones con ese rango.
options(repr.plot.width=7, repr.plot.height=3)
df_ven %>%
group_by(documento) %>%
summarize(n_items = sum(cantidad)) %>%
ggplot(aes(x=n_items))+
geom_histogram(fill="indianred", bins = 300) +
labs(title="ítems por facturas") +
geom_rug()+
coord_cartesian(xlim=c(0,25))
En su mayoría las facturas contienen menos de 5 ítems esto corresponde a mas de 1.000 documentos facturados.
options(repr.plot.width=8, repr.plot.height=6)
theme_set(theme_bw())
df_cot %>%
group_by(DESCRIPCION) %>%
summarize(n_items = sum(Cantidad)) %>%
arrange(desc(n_items)) %>%
head(20) %>%
ggplot(aes(x=DESCRIPCION, y=n_items )) +
geom_bar(stat="identity", width=.5, fill="tomato3") +
labs(title="Cantidad ítems cotizados",
caption="source: Cotizaciones") +
geom_text(aes(label=n_items), position=position_dodge(width=0.9), vjust=-0.25)+
theme(axis.text.x = element_text(angle=65, vjust=0.6))
Revisando por grupo de artículo, las principales cantidades se encuentran en la categoría, piezas de cerradura, piezas filtro, variados, sellos y juntas y variados partes de metal.
theme_set(theme_bw())
df_ven %>%
group_by(pg_descripcion) %>%
summarize(n_items = sum(cantidad)) %>%
arrange(desc(n_items)) %>%
head(20) %>%
ggplot(aes(x=pg_descripcion, y=n_items)) +
geom_bar(stat="identity", width=.5, fill="tomato3") +
labs(title="Cantidad ítems cotizados",
caption="source: Cotizaciones") +
geom_text(aes(label=n_items), position=position_dodge(width=0.9), vjust=-0.25)+
theme(axis.text.x = element_text(angle=65, vjust=0.6))
Las principales cantidades por facturación se encuentra en las piezas de cerradura, piezas filtro, variados, sellos y juntas y variados y piezas de metal. Las categorías tienen un cierto comportamiento similar a las cotizaciones para ello se revisara la tasa de cierre que corresponde a la razón entre los ítems facturados y los ítems cotizados.
df1<-df_cot %>%
group_by(DESCRIPCION) %>%
summarize(n_items = sum(Cantidad)) %>%
arrange(desc(n_items))
df2<-df_ven %>%
group_by(pg_descripcion) %>%
summarize(n_items = sum(cantidad)) %>%
arrange(desc(n_items))
df_ts<-merge(df1, df2, by.x='DESCRIPCION', by.y='pg_descripcion')
options(repr.plot.width=8, repr.plot.height=6)
df_ts %>%
mutate(perc = round(n_items.y / n_items.x,2 )) %>%
head(32) %>%
ggplot(aes(x = DESCRIPCION, y = perc)) +
geom_bar(stat="identity", width=.5, fill="tomato3") +
labs(title="Tasa cierre")+
geom_text(aes(label=perc), position=position_dodge(width=0.9), vjust=-0.25)+
theme(axis.text.x = element_text(angle=65, vjust=0.6))
Al revisar la tasa de cierre de los principales grupos el grupo de cerradura tiene un cierre de un 37%, las piezas de filtro un 81% y los variados sellos y junta un 52%, existen otros grupos con una muy baja tasa como las baterias, piezas marco, rodados y baterias debido a la fuerte competencia en el sector y la existencia de muchas opciones alternativas a diferencia de los que tienen una tasa alta como las piezas de filtro, aceites, piezas elétricas y piezas de desgaste que son mas exclusivas de la marca. Este análisis permite identificar a que grupos que se podría asignar un precio más competitivo y tratar los de zona entre un 30% y 50% de identificar cada material para ver su posterior tasa de cierre individual.
3. Reglas de asociación¶
Usaremos el algoritmo apriori para minar los grupos de items frecuentes y reglas de asociación.
Usaremos como soporte=0.005 y confianza =0.8 para devolver todas las reglas que tienen un soporte de al menos un 0.5% y una confianza de al menos el 80%.
tr_cot<-read.transactions(file="cotizado2.txt", rm.duplicates=TRUE, format="single", sep="\t", col=c(1,2))
rules_cot <- apriori(tr_cot, parameter=list(support=0.005, confidence=0.8))
rules_cot <- sort(rules_cot, by='confidence', decreasing = TRUE)
summary(rules_cot)
El resumen de las reglas para las cotizacionesnos entrega la siguiente información:
- El numero de reglas es 313
- El resumen de la calidad de las medidas, el rango de soporte, confianza y lift.
- El número de transacciones 6257 y su mínimo de parámetro que fueron ingresados anteriormente.
tr_ven<-read.transactions(file="ventas2.txt", rm.duplicates=TRUE, format="single", sep="\t", col=c(1,2))
rules_ven <- apriori(tr_ven, parameter=list(support=0.005, confidence=0.8))
rules_ven <- sort(rules_ven, by='confidence', decreasing = TRUE)
summary(rules_ven)
EL resultado de las reglas para las facturas es diferente ya que con los mismos parámetros de ingreso de 313 reglas pasamos a solo 20, significa que muchas piezas cotizadas el cliente solo compra una parte (las más dificiles de conseguir) y la otras las busca en otro lado ya que puede ser por problema de stock o precio.
Las 10 principales reglas son:
inspect(rules_cot[1:10])
inspect(rules_ven[1:10])
Revisando las reglas en la facturación se puede apreciar que figura los aceites, variados y sellos con filtros, esto basicamente representa las mantenciones a los equipos pero existe un contraste en comparación con las cotizaciones ya que muchas reglas se pierden y como algunas de estas que representan una reparación que incluye piezas de transmisión, cerradura, bujes y sellos, en la facturación solo aparece un subgrupo en la facturación y desaparece el grupo de transmisión.
options(repr.plot.width=8, repr.plot.height=8)
plot(rules_cot, method="grouped", measure=c("support", "confidence"), shading="lift", control=list(k=10))
plot(rules_ven, method="grouped", control=list(k=10))
options(repr.plot.width=6, repr.plot.height=4)
topRules_cot <- rules_cot[1:10];
plot(topRules_cot);
topRules_ven <- rules_ven[1:10];
plot(topRules_ven);
options(repr.plot.width=5, repr.plot.height=5)
plot(topRules_cot, method="graph");
options(repr.plot.width=5, repr.plot.height=5)
plot(topRules_ven, method="graph")
Las siguientes son representaciones gráficas del mismo efecto o como se pierden grupos en la facturación que inicialmente se cotizaban en la facturación. Se puede apreciar como el soporte que representa la cantidad de veces que aparece por factura o cotización pertenece al grupo de filtro, aceites, piezas de cuerpo y desgaste por igual en ambos tipos de documento representado por el tamaño del circulo. El lift representa cual es la probabilidad que estos productos se encuentren juntos representados por el color, mientras mas fuerte es el rojo los productos se encuentran juntos en cada documento así se puede apreciar a simple vista en las cotizaciones que su color es mucho mas intenso en comparación con la facturación final.
4. Conclusión¶
Podemos concluir que existen reglas que estan presentes en las cotizaciones pero que no necesariamente se están aplicando para la facturación, logrando identificarse los grupos de productos y cuales tienen este problema. Como este es el primer análisis el siguiente es identificar que artículos de los grupos que revisamos esta teniendo problema e investigar que puede estar ocurriendo ya que puede ser problema de stock, disponibilidad inmediata o precio.